#region About
/*
 * 2008-06-18 - Gustavo Arjones - gustavo (at) arjones (dot) net
 * 
 * You can copy, use, modify, improve for any propuse
 *  just drop me a mail, I'd like know this code helped someone :)
 * 
 */
#endregion

using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Reflection;
using System.Collections.Specialized;


namespace Arjones.Controls
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
        AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal),
        ToolboxData("<{0}:SWFObject runat=\"server\"> </{0}:SWFObject>")]
    [System.Drawing.ToolboxBitmap(typeof(SWFObject), "SMX.Toolbox.Controls.Res.Flash.bmp")]
    public class SWFObject: System.Web.UI.WebControls.WebControl
    {
        private string _FlashUrl;
        private string _FlashPlayerVer = "9.0.0";
        private string _AlternateContent;
        private string _ExpressInstallUrl;
        private NameValueCollection _FlashVars = new NameValueCollection();
        private NameValueCollection _Params = new NameValueCollection();
        private NameValueCollection _Attributes = new NameValueCollection();

        [Bindable(true), Category("Appearance"), DefaultValue(""),
        Description("Flash File"), Localizable(false)]
        public string FlashUrl
        {
            get { return _FlashUrl; }
            set { _FlashUrl = value; } 
        }

        [Bindable(true), DefaultValue("9.0.0"),
            Description("Specifies the Flash player version your SWF is published for (format is: \"major.minor.release\")"), Localizable(false)]
        public string FlashPlayerVer
        {
            get { return _FlashPlayerVer; }
            set { _FlashPlayerVer = value; }
        }

        [Bindable(true), DefaultValue(""),
            Description(""), Localizable(false)]
        public string AlternateContent
        {
            get { return _AlternateContent; }
            set { _AlternateContent = value; }
        }


        [Bindable(true), DefaultValue(""),
           Description("Specifies the URL of your express install SWF and activates Adobe express install [ http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 ]. Please note that express install will only fire once (the first time that it is invoked), that it is only supported by Flash Player 6.0.65 or higher on Win or Mac platforms, and that it requires a minimal SWF size of 310x137px")]
        public string ExpressInstallUrl
        { 
            get { return _ExpressInstallUrl; } 
            set { _ExpressInstallUrl = value; } 
        }

        [Bindable(true), DefaultValue(""),
            Description(""), Localizable(false)]
        public NameValueCollection FlashVars
        {
            get { return _FlashVars; }
            set { _FlashVars = value; }
        }

        [Bindable(true), DefaultValue(""),
            Description(""), Localizable(false)]
        public NameValueCollection FlashParams
        {
            get { return _Params; }
            set { _Params = value; }
        }

        [Bindable(true), DefaultValue(""),
            Description(""), Localizable(false)]
        public NameValueCollection FlashAttributes
        {
            get { return _Attributes; }
            set { _Attributes = value; }
        }


        /// <summary>
        /// register Javascript during Control Initialization
        /// ref: http://ajaxwidgets.com/more/resources/tutorials/custom_gaia_ajax_webcontrol/cgawcp2.aa
        /// </summary>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (DesignMode) return;

            // get JS from resource file and register to the page
            // register javascripts here
            RegisterClientScriptOnHeader("flashctrl", GetResourceFile("Res.swfobject.js"));
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!DesignMode)
            {
                if (!Page.ClientScript.IsClientScriptBlockRegistered(ClientID))
                {
                    Page.ClientScript.RegisterClientScriptBlock(
                        typeof(SWFObject),
                        ClientID,
                        this.GetFlashVars() + "\n" +
                        this.GetParams() + "\n" +
                        this.GetAttributes() + "\n" +
                        this.EmbedSWF() + "\n",
                        true);
                }
            }
        }


        protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteBeginTag("div");
            writer.WriteAttribute("id", ClientID);

            if (DesignMode && (!Width.IsEmpty && !Height.IsEmpty))
            {
                writer.WriteAttribute("style", String.Format(Res.SWFObject.HtmlStyleDesignTime, this.Width, this.Height));
            }
            writer.Write(HtmlTextWriter.TagRightChar);

            if (DesignMode && this.AlternateContent == null)
            {
                writer.Write("[" + ClientID + "]");
            }
            else
            {
                writer.Write(String.Format("<p>{0}</p>", this.AlternateContent));
            }
            writer.WriteEndTag("div");
        }

        #region "Helper Functions"
        /// <summary>
        /// Returns RESOURCE FILE CONTENT
        /// 
        /// How to read Resources from DLL
        /// ref: http://support.microsoft.com/kb/319292
        /// </summary>
        /// <returns></returns>
        protected string GetResourceFile(string filename)
        {
            Assembly _assembly = Assembly.GetExecutingAssembly();
            StreamReader _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream("Arjones.Controls." + filename));
            return _textStreamReader.ReadToEnd();
        }

        protected void RegisterClientScriptOnHeader(string key, string javascript) {
            // this method garantee only one include on ASP Page
            //
            if (this.Page.Header == null)
                throw new Exception("Missing runat=server attribute on <head> tag.");

            if (this.Page.Header.FindControl(key) == null)
            {
                LiteralControl _lt = new LiteralControl(
                    String.Format("\n" + Res.SWFObject.HtmlScriptTag, "\n" + javascript + "\n") + "\n"
                );
                _lt.ID = key;
                this.Page.Header.Controls.Add(_lt);
            }
        }

        /// <summary>
        /// swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes) 
        /// has five required and four optional arguments:
        /// </summary>
        /// SSSS
        /// see ref: http://code.google.com/p/swfobject/wiki/documentation
        ///     swfUrl (String, required) specifies the URL of your SWF 
        ///     id (String, required) specifies the id of the HTML element (containing your alternative content) you would like to have replaced by your Flash content 
        ///     width (String, required) specifies the width of your SWF 
        ///     height (String, required) specifies the height of your SWF 
        ///     version (String, required) specifies the Flash player version your SWF is published for (format is: "major.minor.release") 
        ///     expressInstallSwfurl (String, optional) specifies the URL of your express install SWF and activates Adobe express install [ http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 ]. Please note that express install will only fire once (the first time that it is invoked), that it is only supported by Flash Player 6.0.65 or higher on Win or Mac platforms, and that it requires a minimal SWF size of 310x137px. 
        ///     flashvars (Object, optional) specifies your flashvars with name:value pairs 
        ///     params (Object, optional) specifies your nested object element params with name:value pairs 
        ///     attributes (Object, optional) specifies your object's attributes with name:value pairs 
        protected string EmbedSWF()
        {
            string _HtmlEmbedSwf = String.Format(Res.SWFObject.HtmlEmbedSwf,
                this.FlashUrl.StartsWith("~") ? VirtualPathUtility.ToAbsolute(this.FlashUrl) : this.FlashUrl,
                this.ClientID,
                this.Width.Value,
                this.Height.Value,
                this.FlashPlayerVer,
                this.ExpressInstallUrl,
                "fv_" + this.ClientID,
                "pr_" + this.ClientID,
                "at_" + this.ClientID
            );

            return _HtmlEmbedSwf;
        }

        /// <summary>
        /// Write JS for Params
        /// </summary>
        protected string GetParams()
        {
            string _Name = "pr_" + this.ClientID;
            return JsObjectDeclaration(_Name, this._Params);
        }


        /// <summary>
        /// Write JS for Attributes
        /// </summary>
        protected string GetAttributes()
        {
            string _Name = "at_" + this.ClientID;
            return JsObjectDeclaration(_Name, this._Attributes);
        }


        /// <summary>
        /// Write JS for Flashvars
        /// </summary>
        protected string GetFlashVars()
        {
            string _Name = "fv_" + this.ClientID;
            return JsObjectDeclaration(_Name, this._FlashVars);
        }


        private string JsObjectDeclaration(string ObjectName, NameValueCollection Attr)
        {
            string _HtmlScriptFlashVars = Res.SWFObject.HtmlScriptObjectDeclare;
            string _Vars = "";


            for (int i = 0; i < Attr.Count; i++)
            {
                _Vars += String.Format("{0}:\"{1}\" ",
                    Attr.Keys[i], Attr[i]);

                _Vars += (i >= Attr.Count -1) ? "" : ", ";
            }

            return String.Format(_HtmlScriptFlashVars,
                ObjectName,
                _Vars
            );
        }


        #endregion

    }
}
